//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#ifndef __MYBMAC_BMACLAYER_H_
#define __MYBMAC_BMACLAYER_H_

#include <omnetpp.h>
#include "BaseMacLayer.h"
#include <DroppedPacket.h>
/**
 * TODO - Generated class
 */
class BmacLayer : public BaseMacLayer
{
  protected:

	//~BMacLayer();

	    /** @brief Initialization of the module and some variables*/
	    virtual void initialize(int);

	    /** @brief Delete all dynamically allocated objects of the module*/
	    virtual void finish();

	    /** @brief Handle messages from lower layer */
	    virtual void handleLowerMsg(cMessage*);

	    /** @brief Handle messages from upper layer */
	    virtual void handleUpperMsg(cMessage*);

	    /** @brief Handle self messages such as timers */
	    virtual void handleSelfMsg(cMessage*);

	    /** @brief Handle control messages from lower layer */
	    virtual void handleLowerControl(cMessage *msg);





  protected:
	    typedef std::list<MacPkt*> MacQueue;
	    /** @brief A queue to store packets from upper layer in case another
	    	packet is still waiting for transmission..*/
	    MacQueue macQueue;
	    unsigned queueLength;

	    /** @name Different tracked statistics.*/
		/*@{*/
		long nbTxDataPackets;
		long nbTxPreambles;
		long nbRxDataPackets;
		long nbRxPreambles;
		long nbMissedAcks;
		long nbRecvdAcks;
		long nbDroppedDataPackets;
		long nbTxAcks;
		/*@}*/
		/** @brief MAC states
			   *
			   *  The MAC states help to keep track what the MAC is actually
			   *  trying to do.
			   *  INIT -- node has just started and its status is unclear
			   *  SLEEP -- node sleeps, but accepts packets from the network layer
			   *  CCA -- Clear Channel Assessment - MAC checks
			   *         whether medium is busy
			   *  SEND_PREAMBLE -- node sends preambles to wake up all nodes
			   *  WAIT_DATA -- node has received at least one preamble from another node and wiats for the actual data packet
			   *  SEND_DATA -- node has sent enough preambles and sends the actual data packet
			   *  WAIT_TX_DATA_OVER -- node waits until the data packet sending is ready
			   *  */
		enum States {
				SLEEP,
		        RX,  	//Receive Data
		        CCA,	//Receive Preamble
		        SEND_PREAMBLE,
		        SEND_DATA,
		        WAIT_TX_DATA_OVER
			};
		States macState;

		//self message types
		enum TYPES {
				BMAC_CONTROL = 191,
				BMAC_WAKEUP ,
				BMAC_SEND_DATA ,
				BMAC_CHECK_CHANNEL,
				BMAC_TIMEOUT_DATA ,
				BMAC_SEND_PREAMBLES ,
				BMAC_STOP_PREAMBLES,
				BMAC_TIMEOUT_PREAMBLES

		};
		//event types
		enum t_mac_event {
		      EV_TIMER_BACKOFF = 150,
		      EV_FRAME_TRANSMITTED,
		      EV_FRAME_RECEIVED,
		      EV_RADIO_SWITCHED,
		      EV_TIMER_WAKEUP,
		      EV_CCA_TIMEOUT,
		      EV_PREAMBLES_TIMEOUT,
		      EV_DATA_TIMEOUT,
		      EV_DATA_SEND
		  };

		// frame recieved types
		 enum t_mac_frame_types {
		    	FRAME_DATA =100,
		    	FRAME_PREAMBLES
		 };

		/** @brief Inspect reasons for dropped packets */
		DroppedPacket droppedPacket;
		/** @brief plus category from BB */
		int catDroppedPacket;
		/** @brief publish dropped packets nic wide */
		int nicId;
		/** @brief Duration of a slot
		     *
		     *  The duty cycle of the node. Every slotDuration it wakes up and checks what's up.
		     */
		double slotDuration;
		/** @brief wake up and listen for control packets */

		/** @brief The duration of CCA */
		double checkInterval;

		/** @brief Transmission power of the node */
		double txPower;
		/** @brief Gather stats at the end of the simulation */
		bool stats;

		cMessage* wakeup;
		/** @brief after wake up, check the channel for some time*/
		cMessage* checkChannel;

		/** @brief */
		/** @brief stop sending control messages, send one data packet*/
		cMessage* sendData;
		/** @brief timeout when false positive*/
		cMessage* timeoutData;
		/** @brief sending currently preambles*/
		cMessage* send_preambles;
		cMessage* stop_preambles;
		/** @brief the bit rate at which we transmit */
		 double bitrate;
		/** @brief change the color of the node or not*/
		bool animation;
		/** @brief send a single preamble packet */
		void sendPreamble();
		/** @brief change the color of the node depending on its state*/
		void changeDisplayColor(char *color);
		/** @brief send datapacket **/
		void sendDataPacket();
		void attachSignal(MacPkt *macPkt);

		int lastDataPktSrcAddr;
		int lastDataPktDestAddr;
		int txAttempts;


  public:
 	    //Those functions is for automaton
		char* State2Name(States state);
 	    void updateMacState(States newMacState);
 	    void executeMac(t_mac_event event,cMessage *msg);
 	    void updateStatusSleep(t_mac_event event,cMessage *msg);
 	    void updateStatusCCA(t_mac_event event,cMessage *msg);
 	    void updateStatusRx(t_mac_event event,cMessage *msg);
 	    void updateStatusSD_PRM(t_mac_event event,cMessage *msg);
 	    void updateStatusSendData(t_mac_event event,cMessage *msg);
 		void updateStatusWaitTxOver(t_mac_event event,cMessage *msg);

  public:
 		bool addToQueue(cMessage *msg);



};

#endif
